﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace UserControls
{
    public partial class UVCanvas : Control
    {
        #region 事件|字段|属性
        //事件
        public event Action<PointF>  ImagePixPointEvent;
        //基本参数
        private Image _image;                               //图像
        private Point _lastMousePosition;                   //鼠标最后位置
        private PointF _imagePosition = new PointF(0, 0);   //图像位置
        private float _zoom = 1.0f;                         //当前缩放
        private const float MinZoom = 0.15f;                //最小缩放
        private const float MaxZoom = 10.0f;                //最大缩放
        private const float ZoomStep = 0.1f;                //缩放步长
        //控件背景棋盘格参数
        private PointF _imagePoint = new PointF(-1.0F, -1.0F);      //图像位置点
        private int controlGridSize = 15;                           // 每个格子的大小
        private Color backColor1 = Color.FromArgb(60, 60, 60);      // 第一种颜色
        private Color backColor2 = Color.FromArgb(80, 80, 80);      // 第二种颜色

        #region 属性
        [Category("UserDefine")]
        [Description("控件显示的图像")]
        public Image Image
        {
            get => _image;
            set
            {
                _image = value;
                CenterImage();
                Invalidate();
            }
        }

        [Category("UserDefine")]
        [Description("当前像素点")]
        [DefaultValue(typeof(double), "-1.0, -1.0")]
        /// <summary>
        /// 当前像素点
        /// </summary>
        public PointF ImagePoint { get => _imagePoint; private set => _imagePoint = value; }

        [Category("UserDefine")]
        [Description("控件网格大小")]
        [DefaultValue("15")]
        public int ControlGridSize { get => controlGridSize; set => controlGridSize = value; }

        [Category("UserDefine")]
        [Description("控件背景色1")]
        [DefaultValue("60, 60, 60")]
        public Color BackColor1 { get => backColor1; set => backColor1 = value; }

        [Category("UserDefine")]
        [Description("控件背景色2")]
        [DefaultValue("80, 80, 80")]
        public Color BackColor2 { get => backColor2; set => backColor2 = value; }
        #endregion

        #endregion

        #region 其他方法
        private PointF ScreenToImage(Point screenPoint)
        {
            return new PointF((screenPoint.X - _imagePosition.X) / _zoom, (screenPoint.Y - _imagePosition.Y) / _zoom);
        }
        /// <summary>
        /// 获取目标矩形
        /// </summary>
        private RectangleF GetDestinationRectangle()
        {
            if (_image == null) return RectangleF.Empty;
            return new RectangleF(_imagePosition.X, _imagePosition.Y, (_image.Width * _zoom), (_image.Height * _zoom));
        }
        /// <summary>
        /// 图像居中
        /// </summary>
        private void CenterImage()
        {
            if (_image == null) return;
            _imagePosition = new PointF((this.Width - _image.Width * _zoom) / 2, (this.Height - _image.Height * _zoom) / 2);
            Invalidate();
        }
        public void ResetImage()
        {
            _zoom = 1.0f;
            CenterImage();
        }
        /// <summary>
        /// 获取像素值
        /// </summary>
        private Color GetPixelColor(PointF imagePoint)
        {
            if (_image == null
                ||imagePoint.X < 0 || imagePoint.X >= _image.Width 
                || imagePoint.Y < 0 || imagePoint.Y >= _image.Height)
            {
                return Color.Empty; // 无效坐标
            }
            // 如果是 Bitmap，直接读取像素
            if (_image is Bitmap bitmap)
            {
                return bitmap.GetPixel((int)imagePoint.X, (int)imagePoint.Y);
            }
            else
            {
                // 如果是其他 Image 类型（如 Metafile），先转换为 Bitmap
                using (Bitmap tempBitmap = new Bitmap(_image))
                {
                    return tempBitmap.GetPixel((int)imagePoint.X, (int)imagePoint.Y);
                }
            }
        }

        #region 绘制网格
        /// <summary>
        /// 绘制控件棋盘格背景
        /// </summary>
        private void DrawControlGridBackgroud(PaintEventArgs e)
        {
            // 获取绘制区域
            Rectangle clipRect = e.ClipRectangle;
            // 计算需要绘制的起始行列
            int startX = (int)(clipRect.Left / ControlGridSize) * ControlGridSize;
            int startY = (int)(clipRect.Top / ControlGridSize) * ControlGridSize;
            // 循环绘制棋盘格
            for (int y = startY; y < clipRect.Bottom; y += ControlGridSize)
            {
                for (int x = startX; x < clipRect.Right; x += ControlGridSize)
                {
                    // 根据位置绘制颜色
                    bool isAlternate = ((x / ControlGridSize) + (y / ControlGridSize)) % 2 == 0;
                    using (Brush brush = new SolidBrush(isAlternate ? BackColor1 : BackColor2))
                    {
                        e.Graphics.FillRectangle(brush, x, y, ControlGridSize, ControlGridSize);
                    }
                }
            }
        }
        #endregion
        #endregion

        #region 初始化
        public UVCanvas()
        {
            this.DoubleBuffered = true;
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true);
        }
        #endregion

        #region 事件方法重写
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            DrawControlGridBackgroud(e);
            if (_image == null) return;
            e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            RectangleF destRect = GetDestinationRectangle();
            e.Graphics.DrawImage(_image, destRect);
            // 新增：绘制当前鼠标位置的图像坐标
            string coordText = $"({ImagePoint.X:F1}, {ImagePoint.Y:F1})";
            // 新增：获取 RGB 值
            Color pixelColor = GetPixelColor(ImagePoint);
            using (var font = new Font("Arial", 10))
            using (var brush = new SolidBrush(Color.Red))
            {
                //判断显示 RGB 值
                if (pixelColor != Color.Empty)
                {
                    string rgbText = $"RGB: ({pixelColor.R}, {pixelColor.G}, {pixelColor.B})";
                    coordText = $"{coordText}\r\n{rgbText}";
                }
                e.Graphics.DrawString(coordText, font, brush, 10, 10);
            }
        }
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            CenterImage();
        }
        protected override void OnDoubleClick(EventArgs e)
        {
            base.OnDoubleClick(e);
            ResetImage();
        }
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (e.Button == MouseButtons.Left && _image != null)
            {
                _lastMousePosition = e.Location;
                this.Cursor = Cursors.Hand;
            }
        }
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            this.Cursor = Cursors.Default;
        }
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (_image != null)
            {
                // 获取图像在屏幕上的绘制区域
                ImagePoint = ScreenToImage(e.Location);
                // 检查鼠标是否在图像区域内
                RectangleF imageRect = GetDestinationRectangle();
                //计算图像坐标（仅在图像区域内计算）
                if (imageRect.Contains(e.Location)){ ImagePoint = ScreenToImage(e.Location);}
                // 不在图像内，设为 (-1, -1)
                else { ImagePoint = new PointF(-1, -1); }
                // 回调图像点
                ImagePixPointEvent?.Invoke(ImagePoint);
                Invalidate();
            }
            if (e.Button == MouseButtons.Left && _image != null)
            {
                // 计算鼠标移动增量
                _imagePosition.X += (e.X - _lastMousePosition.X);
                _imagePosition.Y += (e.Y - _lastMousePosition.Y);
                // 记录鼠标最后位置
                _lastMousePosition = e.Location;
                Invalidate();
            }
        }
        protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);
            if (_image == null) return;
            // 1. 记录缩放前鼠标在 "图像坐标" 中的位置
            PointF mouseInImageSpace = ScreenToImage(e.Location);
            // 2. 计算新的缩放级别
            _zoom += (e.Delta > 0 ? ZoomStep : -ZoomStep);
            _zoom = Math.Max(MinZoom, Math.Min(MaxZoom, _zoom));
            // 3. 计算缩放后该点在屏幕上的新位置（基于鼠标点缩放）
            PointF mouseInScreenSpaceAfterZoom = new PointF(
                mouseInImageSpace.X * _zoom + _imagePosition.X,
                mouseInImageSpace.Y * _zoom + _imagePosition.Y);
            // 4. 计算偏移量，使鼠标下的点仍然在原来的屏幕位置
            _imagePosition.X += (e.Location.X - mouseInScreenSpaceAfterZoom.X);
            _imagePosition.Y += (e.Location.Y - mouseInScreenSpaceAfterZoom.Y);
            // 更新显示
            Invalidate();
        }
        #endregion
    }
}
